From c10797216b26af4328de6761275dfa8fd21736ff Mon Sep 17 00:00:00 2001 From: "sos22@douglas.cl.cam.ac.uk" Date: Fri, 2 Dec 2005 15:16:37 +0100 Subject: [PATCH] Avoid a hang when probing the partition table on imported block devices. If you export a device so the importing domain sees it as a whole disk rather than a partition, then add_disk will try to probe its partition table. However, we were calling add_disk before the device was properly connected, and then not connecting it until add_disk had finished. This meant that we ended up never actually connecting the device, and any accesses to it would then hang. Fix this by not calling add_disk until we're connected. Signed-off-by: Steven Smith, sos22@cam.ac.uk --- linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c | 9 +++++---- linux-2.6-xen-sparse/drivers/xen/blkfront/block.h | 3 +++ linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c | 1 - 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c index e7afc76b8e..6c9e5b6480 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/blkfront.c @@ -311,7 +311,7 @@ static void connect(struct blkfront_info *info) int err; if( (info->connected == BLKIF_STATE_CONNECTED) || - (info->connected == BLKIF_STATE_SUSPENDED) ) + (info->connected == BLKIF_STATE_SUSPENDED) ) return; DPRINTK("blkfront.c:connect:%s.\n", info->xbdev->otherend); @@ -327,16 +327,18 @@ static void connect(struct blkfront_info *info) info->xbdev->otherend); return; } - + xlvbd_add(sectors, info->vdevice, binfo, sector_size, info); (void)xenbus_switch_state(info->xbdev, NULL, XenbusStateConnected); - + /* Kick pending requests. */ spin_lock_irq(&blkif_io_lock); info->connected = BLKIF_STATE_CONNECTED; kick_pending_request_queues(info); spin_unlock_irq(&blkif_io_lock); + + add_disk(info->gd); } /** @@ -588,7 +590,6 @@ void do_blkif_request(request_queue_t *rq) while ((req = elv_next_request(rq)) != NULL) { info = req->rq_disk->private_data; - if (!blk_fs_request(req)) { end_request(req, 0); continue; diff --git a/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h b/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h index 809451aec7..3809f9067b 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/block.h @@ -146,6 +146,9 @@ extern int blkif_revalidate(dev_t dev); extern void do_blkif_request (request_queue_t *rq); /* Virtual block-device subsystem. */ +/* Note that xlvbd_add doesn't call add_disk for you: you're expected + to call add_disk on info->gd once the disk is properly connected + up. */ int xlvbd_add(blkif_sector_t capacity, int device, u16 vdisk_info, u16 sector_size, struct blkfront_info *info); void xlvbd_del(struct blkfront_info *info); diff --git a/linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c b/linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c index 47ebba39f2..d97f798e6f 100644 --- a/linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c +++ b/linux-2.6-xen-sparse/drivers/xen/blkfront/vbd.c @@ -261,7 +261,6 @@ xlvbd_alloc_gendisk(int minor, blkif_sector_t capacity, int vdevice, if (vdisk_info & VDISK_CDROM) gd->flags |= GENHD_FL_CD; - add_disk(gd); info->gd = gd; return 0; -- 2.30.2